/**
 * Project: core.common
 * 
 * File Created at 2016年4月5日
 * 
 * Copyright 2015-2015 dx.com Croporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * DongXue software Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with dx.com.
 */
package com.dx.pf.commons.balance;

import java.util.List;

/** 
* @ClassName: RoundBalancer 
* @Description: 环形负载方式，请求平均分布，单台服务器故障时，不影响使用，可以重新请求，保证请求可以处理（每次请求访问的节点都是不同的）
 * 支持节点动态的摘除和增加
 * 支持uri的动态变化
* @author wuzhenfang(wzfbj2008@163.com)
* @date 2016年4月5日 上午12:25:11 
* @version V1.0 
*/
public class RoundBalancer implements IBalancer {
	private static volatile RoundBalancer instance = null;

    private RoundBalancer() {
        System.out.println("BalanceCore初始化成功>>>");
    }

    /**
     * 获取Balancer对象
     *
     * @return RoundBalancer
     */
    public static RoundBalancer getInstance() {
        if (instance == null) { // double check (jdk1.5+)
            synchronized (Context.class) {
                if (instance == null)
                    instance = new RoundBalancer();
            }
        }
        return instance;
    }

    /**
     * 热门uri路由,这是对外使用的方法入口
     *
     * @param uriStr 热门uri
     * @return 路由节点
     */
    public ServerNode navigate(String uriStr) {
    	ServerNode node = null;
        if (null == uriStr) return null;
        uriStr = uriStr.trim();
        if ("".equals(uriStr)) return null;
        Context context = Context.getInstance();
        List<ServerNode> atsServers = context.getAtsServers();
        if (atsServers == null || atsServers.isEmpty()) {
            System.out.println("未设置ats服务器列表!");
            return null;
        }
        long hashCode = context.hash(uriStr);
        if (context.getUriHashMap().containsKey(hashCode)) {
            int index = context.getUriHash(hashCode);
            if (index < atsServers.size() - 1) {
                index++;
            } else index = 0;
            Context.getInstance().putUriHash(hashCode, index); //记录索引值
            return atsServers.get(index);
        }
        return node;
    }
}
